/*
 * 项目名称:    wms-server-jeecg
 * 创建人员:    gongwenkai
 * 创建时间:    2023-11-24
 */
package org.jeecg.modules.flow.callback.delivery.util;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.basic.warehouse.entity.WmsBasicWarehouseArea;
import org.jeecg.modules.basic.warehouse.service.IWmsBasicWarehouseAreaService;
import org.jeecg.modules.business.delivery.entity.WmsDeliveryTask;
import org.jeecg.modules.business.delivery.entity.WmsDeliveryTaskMaterial;
import org.jeecg.modules.business.delivery.service.IWmsDeliveryTaskMaterialService;
import org.jeecg.modules.business.delivery.service.IWmsDeliveryTaskService;
import org.jeecg.modules.business.doc.business.entity.WmsInReceiptMaterial;
import org.jeecg.modules.business.outbound.entity.WmsOutReceiptTask;
import org.jeecg.modules.business.outbound.entity.WmsOutReceiptTaskMaterial;
import org.jeecg.modules.business.outbound.service.IWmsOutReceiptTaskMaterialService;
import org.jeecg.modules.business.outbound.service.IWmsOutReceiptTaskService;
import org.jeecg.modules.business.repertory.entity.WmsInTransitRepertory;
import org.jeecg.modules.business.repertory.service.IWmsInTransitRepertoryService;
import org.jeecg.modules.business.third.service.INestStatusService;
import org.jeecg.modules.business.transfer.entity.WmsMoveReceiptMaterial;
import org.jeecg.modules.business.warehouse.entity.WmsInReceiptTask;
import org.jeecg.modules.business.warehouse.entity.WmsInReceiptTaskMaterial;
import org.jeecg.modules.business.warehouse.service.IWmsInReceiptTaskMaterialService;
import org.jeecg.modules.business.warehouse.service.IWmsInReceiptTaskService;
import org.jeecg.modules.dock.entity.nest.NestBaseRequestVO;
import org.jeecg.modules.dock.entity.nest.NestUpdateStatusVO;
import org.jeecg.modules.flow.callback.enums.SimpleDocumentTypeEnum;
import org.jeecg.modules.flow.callback.enums.WarehouseAreaTypeEnum;
import org.jeecg.modules.flow.sys.entity.dto.BaseFlowDto;
import org.jeecg.modules.flow.sys.service.WorkFlowService;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 通用调拨任务工具类
 *
 * @author gongwenkai
 * @version 1.0.0
 * @since 2023-11-24
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class CommonDeliveryTaskUtil {

    private final IWmsOutReceiptTaskService outReceiptTaskService;

    private final IWmsOutReceiptTaskMaterialService outReceiptTaskMaterialService;

    private final IWmsDeliveryTaskService deliveryTaskService;

    private final IWmsDeliveryTaskMaterialService deliveryTaskMaterialService;

    private final IWmsInReceiptTaskService inReceiptTaskService;

    private final IWmsInReceiptTaskMaterialService inReceiptTaskMaterialService;

    private final WorkFlowService workFlowService;
    private final INestStatusService iNestStatusService;

    private final IWmsBasicWarehouseAreaService warehouseAreaService;

    private final IWmsInTransitRepertoryService inTransitRepertoryService;

    /**
     * 一二期到四期调拨任务出库节点代码
     */
    private final String deliveryTaskDB1OutCode="8aaa80ae8bf9d477018bf9d670520004";

    /**
     * 四期到一二期调拨任务出库节点代码
     */
    private final String deliveryTaskDB2OutCode="8aaa80ae8bf9d477018bf9d4cb240001";

    /**
     * 调拨任务业务类型
     */
    private final String deliveryBusinessType="delivery_task";

    /**
     * 一二期到四期调拨任务入库节点代码
     */
    private final String deliveryTaskDB1InCode="8aaa80ca8bfb2d31018bfb2d31080000";

    /**
     * 四期到一二期调拨任务入库节点代码
     */
    private final String deliveryTaskDB2InCode="8aaa80cb8bfb2e5f018bfb2e5f040000";


    public WmsDeliveryTask getDeliveryTaskByOutTaskId(String outTaskId){
        WmsOutReceiptTask outReceiptTask = outReceiptTaskService.getById(outTaskId);
        if(Objects.isNull(outReceiptTask)){
            throw new JeecgBootException("出库任务不存在");
        }else{
            String documentCode = outReceiptTask.getDocumentCode();
            WmsDeliveryTask deliveryTask = deliveryTaskService.getOne(new LambdaQueryWrapper<WmsDeliveryTask>()
                    .eq(WmsDeliveryTask::getOutTaskCode, documentCode)
            );
            if(Objects.isNull(deliveryTask )){
                throw new JeecgBootException("调拨任务不存在");
            }else{
                return deliveryTask;
            }
        }
    }

    public String getDeliveryIdTaskByOutTaskId(String outTaskId){
        return  getDeliveryTaskByOutTaskId(outTaskId).getId();
    }

    public WmsDeliveryTask getDeliveryTaskByInTaskId(String inTaskId){
        WmsInReceiptTask wmsInReceiptTask = inReceiptTaskService.getById(inTaskId);
        if(Objects.isNull(wmsInReceiptTask)){
            throw new JeecgBootException("入库任务不存在");
        }else{
            String documentCode = wmsInReceiptTask.getDocumentCode();
            WmsDeliveryTask deliveryTask = deliveryTaskService.getOne(new LambdaQueryWrapper<WmsDeliveryTask>()
                    .eq(WmsDeliveryTask::getInTaskCode, documentCode)
            );
            if(Objects.isNull(deliveryTask )){
                throw new JeecgBootException("调拨任务不存在");
            }else{
                return deliveryTask;
            }
        }
    }

    public String getDeliveryTaskIdByInTaskId(String inTaskId){
        return getDeliveryTaskByInTaskId(inTaskId).getId();
    }



    /**
     * 构建出库流程节点需要的数据
     * @return
     */
    private BaseFlowDto buildOutFlowDto(String outTaskId){
        WmsDeliveryTask deliveryTask = getDeliveryTaskByOutTaskId(outTaskId);

        BaseFlowDto baseFlowDto=new BaseFlowDto();
        baseFlowDto.setInfoId(deliveryTask.getId());
        baseFlowDto.setBusinessType(deliveryBusinessType);
        baseFlowDto.setDocumentType(deliveryTask.getDocumentType());
        if("DB1".equals(deliveryTask.getDocumentType())){
            baseFlowDto.setCode(deliveryTaskDB1OutCode);
        }else if("DB2".equals(deliveryTask.getDocumentType())){
            baseFlowDto.setCode(deliveryTaskDB2OutCode);
        }else{
            throw new JeecgBootException("调拨单据类型不存在");
        }
        return baseFlowDto;
    }

    /**
     * 构建出库流程节点需要的数据
     * @return
     */
    private BaseFlowDto buildInFlowDto(String inTaskId){
        WmsDeliveryTask deliveryTask = getDeliveryTaskByInTaskId(inTaskId);

        BaseFlowDto baseFlowDto=new BaseFlowDto();
        baseFlowDto.setInfoId(deliveryTask.getId());
        baseFlowDto.setBusinessType(deliveryBusinessType);
        baseFlowDto.setDocumentType(deliveryTask.getDocumentType());
        if("DB1".equals(deliveryTask.getDocumentType())){
            baseFlowDto.setCode(deliveryTaskDB1InCode);
        }else if("DB2".equals(deliveryTask.getDocumentType())){
            baseFlowDto.setCode(deliveryTaskDB2InCode);
        }else{
            throw new JeecgBootException("调拨单据类型不存在");
        }
        return baseFlowDto;
    }

    /**
     * 推动调拨任务的出库节点
     * @param outTaskId
     */
    public void pushOutFlow(String outTaskId){
        BaseFlowDto baseFlowDto = buildOutFlowDto(outTaskId);
        workFlowService.commit(baseFlowDto);
    }

    /**
     * 推动调拨任务的入库节点
     * @param inTaskId
     */
    public void pushInFlow(String inTaskId){
        BaseFlowDto baseFlowDto = buildInFlowDto(inTaskId);
        workFlowService.commit(baseFlowDto);
    }


    /**
     * 更新物料的调拨状态
     * @param type
     * @param taskId
     * @param taskMaterialId
     * @param status
     * @param jsonData
     */
    public void updateMaterialDeliveryStatus(SimpleDocumentTypeEnum type, String taskId, String taskMaterialId, String status, JSONObject jsonData){
        try{
            if(type==SimpleDocumentTypeEnum.OUT_TASK){
                //从调拨出库任务的流程节点来的
                LambdaQueryWrapper<WmsOutReceiptTaskMaterial> queryWrapper = new LambdaQueryWrapper<WmsOutReceiptTaskMaterial>()
                        .eq(WmsOutReceiptTaskMaterial::getWmsOutReceiptTaskId, taskId);
                if(!StrUtil.isEmpty(taskMaterialId)){
                    queryWrapper.eq(WmsOutReceiptTaskMaterial::getId,taskMaterialId);
                }
                List<WmsOutReceiptTaskMaterial> taskMaterialList = outReceiptTaskMaterialService.list(queryWrapper);
                if(CollectionUtil.isEmpty(taskMaterialList)){
                    return;
                }
                for(WmsOutReceiptTaskMaterial taskMaterial:taskMaterialList){
                    //1 根据出库任务的物料明细去找到调拨任务的物料
                    if(Objects.isNull(taskMaterial)|| StrUtil.isEmpty(taskMaterial.getTransferApplicationOrder())){
                        //如果出库任务物料为空或者出库任务物料的调拨单号为空，直接不做处理
                        return;
                    }
                    WmsDeliveryTask deliveryTask = deliveryTaskService.getOne(new LambdaQueryWrapper<WmsDeliveryTask>()
                            .eq(WmsDeliveryTask::getDocumentCode, taskMaterial.getTransferApplicationOrder()));
                    if(Objects.isNull(deliveryTask)){
                        //如果找不到调拨任务，直接不做处理
                        return;
                    }
                    List<WmsDeliveryTaskMaterial> deliveryTaskMaterialList = deliveryTaskMaterialService.list(new LambdaQueryWrapper<WmsDeliveryTaskMaterial>()
                            .eq(WmsDeliveryTaskMaterial::getWmsDeliveryTaskId, deliveryTask.getId())
                            .eq(WmsDeliveryTaskMaterial::getBatchCode,taskMaterial.getBatchCode())
                    );
                    if(CollectionUtil.isEmpty(deliveryTaskMaterialList)){
                        return;
                    }else if(deliveryTaskMaterialList.size()>1){
                        log.error("警告!更新物料的调拨状态,相同批次号匹配到的物料超过一条!数据为{}",deliveryTaskMaterialList);
                    }
                    WmsDeliveryTaskMaterial deliveryTaskMaterial = deliveryTaskMaterialList.get(0);
                    //2 更新调拨任务物料明细中的状态
                    deliveryTaskMaterial.setDeliveryStatus(status);
                    deliveryTaskMaterialService.updateById(deliveryTaskMaterial);
                    //3 todo 范志文通知套裁系统
                    boolean result = noticeNest(deliveryTask, deliveryTaskMaterial);
                }
            }
            if(type==SimpleDocumentTypeEnum.IN_TASK){
                //从调拨入库任务节点来的
                LambdaQueryWrapper<WmsInReceiptTaskMaterial> queryWrapper = new LambdaQueryWrapper<WmsInReceiptTaskMaterial>()
                        .eq(WmsInReceiptTaskMaterial::getWmsInReceiptTaskId, taskId);
                if(!StrUtil.isEmpty(taskMaterialId)){
                    queryWrapper.eq(WmsInReceiptTaskMaterial::getId,taskMaterialId);
                }
                List<WmsInReceiptTaskMaterial> taskMaterialList = inReceiptTaskMaterialService.list(queryWrapper);
                if(CollectionUtil.isEmpty(taskMaterialList)){
                    return;
                }
                for(WmsInReceiptTaskMaterial taskMaterial:taskMaterialList){
                    //1 根据入库任务的物料明细去找到调拨任务的物料
                    if(Objects.isNull(taskMaterial)|| StrUtil.isEmpty(taskMaterial.getTransferApplicationOrder())){
                        //如果入库任务物料为空或者入库任务物料的调拨单号为空，直接不做处理
                        return;
                    }
                    WmsDeliveryTask deliveryTask = deliveryTaskService.getOne(new LambdaQueryWrapper<WmsDeliveryTask>()
                            .eq(WmsDeliveryTask::getDocumentCode, taskMaterial.getTransferApplicationOrder()));
                    if(Objects.isNull(deliveryTask)){
                        //如果找不到调拨任务，直接不做处理
                        return;
                    }
                    List<WmsDeliveryTaskMaterial> deliveryTaskMaterialList = deliveryTaskMaterialService.list(new LambdaQueryWrapper<WmsDeliveryTaskMaterial>()
                            .eq(WmsDeliveryTaskMaterial::getWmsDeliveryTaskId, deliveryTask.getId())
                            .eq(WmsDeliveryTaskMaterial::getBatchCode,taskMaterial.getBatchCode())
                    );
                    if(CollectionUtil.isEmpty(deliveryTaskMaterialList)){
                        return;
                    }else if(deliveryTaskMaterialList.size()>1){
                        log.error("警告!更新物料的调拨状态,相同批次号匹配到的物料超过一条!数据为{}",deliveryTaskMaterialList);
                    }
                    WmsDeliveryTaskMaterial deliveryTaskMaterial = deliveryTaskMaterialList.get(0);
                    //2 更新调拨任务物料明细中的状态
                    deliveryTaskMaterial.setDeliveryStatus(status);
                    deliveryTaskMaterialService.updateById(deliveryTaskMaterial);
                    //3 todo 范志文通知套裁系统
                    boolean result = noticeNest(deliveryTask, deliveryTaskMaterial);
                }
            }
            if(type==SimpleDocumentTypeEnum.MOVE_RECEIPT){
                //从调拨移库单节点来的
                return;
            }
            if(type==SimpleDocumentTypeEnum.DELIVERY_TASK){
                //从调拨任务的流程节点来的
                return;
            }

        }catch (Exception e){
            log.error("更新物料的调拨状态发生错误{}",e.getMessage());
        }
    }
    /**
     *  通知套裁系统
     */
    private boolean noticeNest(WmsDeliveryTask deliveryTask,WmsDeliveryTaskMaterial deliveryTaskMaterial){
        List<NestBaseRequestVO.Body> detailList = new ArrayList<>();
        NestBaseRequestVO.Body detail = new NestBaseRequestVO.Body();
        detail.setTaskCode(deliveryTask.getTaskCode());
        detail.setBatchCode(deliveryTaskMaterial.getBatchCode());
        detail.setStatus(deliveryTaskMaterial.getDeliveryStatus());
        try {
            LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            detail.setOperatorName(sysUser.getRealname());
        }catch (Exception e){
            detail.setOperatorName("WMS人员");
        }
        detail.setOperateTime(new Date());
        detailList.add(detail);
        NestUpdateStatusVO nestUpdateStatusVO = iNestStatusService.updateStatus(detailList);
        if (ObjectUtil.isNotNull(nestUpdateStatusVO)){
            if ("S".equals(nestUpdateStatusVO.getHeader().getCode())){
                return true;
            }
        }
        return false;
    }

    /**
     * r101 一二期到四期入库单需要校验入到临时库区
     */
    public void checkInReceiptMaterialWarehouseArea(String documentType,List<WmsInReceiptMaterial> receiptMaterialList){
        if(StrUtil.isEmpty(documentType)){
            return;
        }
        if(!"R101".equals(documentType)){
            return;
        }
        //只有R101入库单进行校验
        if(!CollectionUtil.isEmpty(receiptMaterialList)){
            for(WmsInReceiptMaterial receiptMaterial:receiptMaterialList){
                if(StrUtil.isEmpty(receiptMaterial.getWmsBasicWarehouseAreaId())){
                    throw new JeecgBootException("该入库单物料存入库区不能为空");
                }
                WmsBasicWarehouseArea warehouseArea = warehouseAreaService.getById(receiptMaterial.getWmsBasicWarehouseAreaId());
                if(Objects.isNull(warehouseArea)){
                    throw new JeecgBootException("该入库单物料存库区不存在");
                }
                if(!WarehouseAreaTypeEnum.TEMP_AREA.getCode().equals(warehouseArea.getAreaType())){
                    throw new JeecgBootException("该入库单物料存库区不是临时库区");
                }
            }
        }
    }

    public void checkMoveReceiptMaterialWarehouseArea(String documentType,List<WmsMoveReceiptMaterial> receiptMaterialList){
        if(StrUtil.isEmpty(documentType)){
            return;
        }
        if(!"Y106".equals(documentType)){
            return;
        }
        //只有R101入库单进行校验
        if(!CollectionUtil.isEmpty(receiptMaterialList)){
            for(WmsMoveReceiptMaterial receiptMaterial:receiptMaterialList){
                if(StrUtil.isEmpty(receiptMaterial.getTransferToAreaId())){
                    throw new JeecgBootException("该移库单物料调入库区不能为空");
                }
                WmsBasicWarehouseArea warehouseArea = warehouseAreaService.getById(receiptMaterial.getTransferToAreaId());
                if(Objects.isNull(warehouseArea)){
                    throw new JeecgBootException("该移库单物料存库区不存在");
                }
                if(!WarehouseAreaTypeEnum.TEMP_AREA.getCode().equals(warehouseArea.getAreaType())){
                    throw new JeecgBootException("该移库单物料存库区不是临时库区");
                }
            }
        }
    }

    /**
     * r101 r105 保存创建出库单
     * @param wmsInReceiptTaskId
     */
    public void checkExistInTransitRepertory(String wmsInReceiptTaskId) {
        WmsInReceiptTask wmsInReceiptTask = inReceiptTaskService.getById(wmsInReceiptTaskId);
        if(Objects.isNull(wmsInReceiptTask)){
            return;
        }
        WmsDeliveryTask wmsDeliveryTask = deliveryTaskService.getOne(new LambdaQueryWrapper<WmsDeliveryTask>()
                .eq(WmsDeliveryTask::getInTaskCode, wmsInReceiptTask.getDocumentCode())
                .last("LIMIT 1")
        );
        if(Objects.isNull(wmsDeliveryTask)){
            return;
        }
        long count = inTransitRepertoryService.count(new LambdaQueryWrapper<WmsInTransitRepertory>().eq(WmsInTransitRepertory::getDeliveryTaskId, wmsDeliveryTask.getId()));
        if(count==0){
            throw new JeecgBootException("请先出库再入库!");
        }
    }
}
